package com.cqie.hospitalescort.utils;


import org.apache.commons.lang3.StringUtils;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
 * 日期操作辅助类
 *
 * @author ShenHuaJie
 * @version $Id: DateUtil.java, v 0.1 2014年3月28日 上午8:58:11 ShenHuaJie Exp $
 */
public final class DateUtil {
    private DateUtil() {
    }

    public static final String YEAR = "year";
    public static final String MONTH = "month";
    public static final String DAY = "day";
    public static final String HOUR = "hour";
    public static final String MINUTE = "minute";
    public static final String SECOND = "second";
    public static final String DEFAULT_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DATE_FORMAT = "yyyy-MM-dd";
    public static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final String DATETIME_FORMAT_T = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";

    /** 日期格式 **/
    public interface DATE_PATTERN {
        String HHMMSS = "HHmmss";

        String HH_MM_SS = "HH:mm:ss";

        String YYYYMMDD = "yyyyMMdd";

        String YYYY_MM_DD = "yyyy-MM-dd";

        String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

        String YYYYMMDDHHMMSSSSS = "yyyyMMddHHmmssSSS";

        String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
    }

    /**
     * 格式化日期
     *
     * @param date
     * @return
     */
    public static final String format(Object date)
    {
        return format(date, DATE_PATTERN.YYYY_MM_DD);
    }

    /**
     * 格式化日期
     *
     * @param date
     * @param pattern
     * @return
     */
    public static final String format(Object date, String pattern) {
        if (date == null)
        {
            return null;
        }
        if (pattern == null)
        {
            return format(date);
        }
        return new SimpleDateFormat(pattern).format(date);
    }

    /**
     * 获取日期
     *
     * @return
     */
    public static final String getDate()
    {
        return format(new Date());
    }

    /**
     * 获取日期
     *
     * @return
     */
    public static final Date getNowDate()
    {
        return new Date();
    }

    /**
     * 获取日期时间
     *
     * @return
     */
    public static final String getDateTime()
    {
        return format(new Date(), DATE_PATTERN.YYYY_MM_DD_HH_MM_SS);
    }

    /**
     * 获取日期时间
     *
     * @return
     */
    public static final String getDateHMD()
    {
        return format(new Date(), DATE_PATTERN.YYYY_MM_DD);
    }

    /**
     * 获取日期
     *
     * @param pattern
     * @return
     */
    public static final String getDateTime(String pattern)
    {
        return format(new Date(), pattern);
    }

    /**
     * 日期计算
     *
     * @param date
     * @param field
     * @param amount
     * @return
     */
    public static final Date addDate(Date date, int field, int amount)
    {
        if (date == null)
        {
            return null;
        }
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(field, amount);
        return calendar.getTime();
    }

    /**
     * 字符串转换为日期:不支持yyM[M]d[d]格式
     *
     * @param date
     * @return
     */
    public static final Date stringToDate(String date)
    {
        if (date == null)
        {
            return null;
        }
        String separator = String.valueOf(date.charAt(4));
        String pattern = "yyyyMMdd";
        if (!separator.matches("\\d*"))
        {
            pattern = "yyyy" + separator + "MM" + separator + "dd";
            if (date.length() < 10)
            {
                pattern = "yyyy" + separator + "M" + separator + "d";
            }
        }
        else if (date.length() < 8)
        {
            pattern = "yyyyMd";
        }
        pattern += " HH:mm:ss.SSS";
        pattern = pattern.substring(0, Math.min(pattern.length(), date.length()));
        try
        {
            return new SimpleDateFormat(pattern).parse(date);
        }
        catch (ParseException e)
        {
            return null;
        }
    }

    /**
     * 间隔天数
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static final Integer getDayBetween(Date startDate, Date endDate)
    {
        Calendar start = Calendar.getInstance();
        start.setTime(startDate);
        start.set(Calendar.HOUR_OF_DAY, 0);
        start.set(Calendar.MINUTE, 0);
        start.set(Calendar.SECOND, 0);
        start.set(Calendar.MILLISECOND, 0);
        Calendar end = Calendar.getInstance();
        end.setTime(endDate);
        end.set(Calendar.HOUR_OF_DAY, 0);
        end.set(Calendar.MINUTE, 0);
        end.set(Calendar.SECOND, 0);
        end.set(Calendar.MILLISECOND, 0);

        long n = end.getTimeInMillis() - start.getTimeInMillis();
        return (int) (n / (60 * 60 * 24 * 1000l));
    }

    /**
     * 间隔月
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static final Integer getMonthBetween(Date startDate, Date endDate)
    {
        if (startDate == null || endDate == null || !startDate.before(endDate))
        {
            return null;
        }
        Calendar start = Calendar.getInstance();
        start.setTime(startDate);
        Calendar end = Calendar.getInstance();
        end.setTime(endDate);
        int year1 = start.get(Calendar.YEAR);
        int year2 = end.get(Calendar.YEAR);
        int month1 = start.get(Calendar.MONTH);
        int month2 = end.get(Calendar.MONTH);
        int n = (year2 - year1) * 12;
        n = n + month2 - month1;
        return n;
    }

    /**
     * 间隔月，多一天就多算一个月
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static final Integer getMonthBetweenWithDay(Date startDate, Date endDate)
    {
        if (startDate == null || endDate == null || !startDate.before(endDate))
        {
            return null;
        }
        Calendar start = Calendar.getInstance();
        start.setTime(startDate);
        Calendar end = Calendar.getInstance();
        end.setTime(endDate);
        int year1 = start.get(Calendar.YEAR);
        int year2 = end.get(Calendar.YEAR);
        int month1 = start.get(Calendar.MONTH);
        int month2 = end.get(Calendar.MONTH);
        int n = (year2 - year1) * 12;
        n = n + month2 - month1;
        int day1 = start.get(Calendar.DAY_OF_MONTH);
        int day2 = end.get(Calendar.DAY_OF_MONTH);
        if (day1 <= day2)
        {
            n++;
        }
        return n;
    }

    /**
     * 获取一天的开始时间
     * @return
     */
    public static Date getDayBegin(){
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.MILLISECOND, 001);
        return new Date(cal.getTimeInMillis());
    }

    /**
     * 在当前时间基础上加一天
     * @param date
     * @return
     */
    public static Date getDatePlusOneDay(Date date){
        Calendar cal = new GregorianCalendar();
        cal.setTime(date);
        cal.add(cal.DATE,1);
        return cal.getTime();
    }

    public static final ThreadLocal<DateFormat> TH_DATE_FORMAT = new ThreadLocal<DateFormat>() {
        protected DateFormat initialValue() {
            return new SimpleDateFormat(DATE_PATTERN.YYYY_MM_DD);
        }
    };

    /**
     * 获取当前时间的字符串形式
     *
     * @since 2017年7月28日
     * @param format
     *            转换格式，为null时使用默认格式yyyy-MM-dd HH:mm:ss
     * @return
     */
    public static String getCurrentDate(String format) {
        if (format == null) {
            format = DEFAULT_FORMAT;
        }
        SimpleDateFormat formatter = new SimpleDateFormat(format);
        return formatter.format(new Date());
    }

    /**
     * 将字符串格式的时间转换成时间对象
     *
     * @since 2017年10月20日
     * @param dateStr
     *            字符串格式的时间
     * @param format
     *            转换格式，为null时使用默认格式yyyy-MM-dd HH:mm:ss
     * @return
     * @throws Exception
     */
    public static Date strToDate(String dateStr, String format) throws Exception {
        if (StringUtils.isBlank(dateStr)) {
            return null;
        }
        if (format == null) {
            if (dateStr.indexOf(":") == -1) {
                format = DATE_FORMAT;
            } else {
                format = DATETIME_FORMAT;
            }
        }
        SimpleDateFormat formatter = new SimpleDateFormat(format);
        return formatter.parse(dateStr);
    }

    /**
     * 将字符串格式的时间转换成时间对象 2018-03-22T16:00:00.000Z
     *
     * @since 2018年3月23日
     * @param dateStr
     * @return
     * @throws Exception
     */
    public static Date strToDateForT(String dateStr) throws Exception {
        dateStr = dateStr.replace("Z", " UTC");
        SimpleDateFormat format = new SimpleDateFormat(DATETIME_FORMAT_T);
        return format.parse(dateStr);
    }

    /**
     * 将时间对象转换成字符串
     *
     * @since 2017年11月14日
     * @param date
     * @param format
     *            转换格式，为null时使用默认格式yyyy-MM-dd HH:mm:ss
     * @return
     * @throws Exception
     */
    public static String dateToStr(Date date, String format) throws Exception {
        if (date == null) {
            return null;
        }
        if (format == null) {
            format = DEFAULT_FORMAT;
        }
        SimpleDateFormat formatter = new SimpleDateFormat(format);
        return formatter.format(date);
    }

    /**
     * date转换成long，考虑date为null的情况
     *
     * @since 2017年11月8日
     * @param date
     * @return
     * @throws Exception
     */
    public static long dateToLong(Date date) throws Exception {
        if (date == null) {
            return 0;
        }
        return date.getTime();
    }

    /**
     * long转换成date，考虑long为0的情况
     *
     * @since 2017年11月8日
     * @param date
     * @return
     * @throws Exception
     */
    public static Date longToDate(long date) throws Exception {
        if (date == 0) {
            return null;
        }
        return new Date(date);
    }

    /***
     *
     * @param date
     *            原时间
     * @param num
     *            相加的值
     * @param type
     *            类型： DateUtil.YEAR: 年; DateUtil.MONTH: 月; DateUtil.DAY: 日;
     *            DateUtil.HOUR: 时; DateUtil.MINUTE: 分; DateUtil.SECOND: 秒;
     * @return
     */
    public static Date addDate(Date date, int num, String type) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        if (type.equals(SECOND)) {
            c.set(Calendar.SECOND, c.get(Calendar.SECOND) + num);
        } else if (type.equals(MINUTE)) {
            c.set(Calendar.MINUTE, c.get(Calendar.MINUTE) + num);
        } else if (type.equals(HOUR)) {
            c.set(Calendar.HOUR_OF_DAY, c.get(Calendar.HOUR_OF_DAY) + num);
        } else if (type.equals(DAY)) {
            c.set(Calendar.DAY_OF_MONTH, c.get(Calendar.DAY_OF_MONTH) + num);
        } else if (type.equals(MONTH)) {
            c.set(Calendar.MONTH, c.get(Calendar.MONTH) + num);
        } else if (type.equals(YEAR)) {
            c.set(Calendar.YEAR, c.get(Calendar.YEAR) + num);
        }
        return c.getTime();
    }

    /**
     * 检测value是否是时间字符串，是则转换成date对象，否返回value
     *
     * @since 2018年3月21日
     * @param value
     * @return
     */
    public static Object objStrToDate(Object value) {
        if (value != null) {
            if (value instanceof String) {
                String valueStr = (String) value;
                if (valueStr.split("-").length == 3) {
                    if (valueStr.split(":").length == 3) {
                        if(valueStr.indexOf("T") != -1 && valueStr.indexOf("Z") != -1){
                            try {
                                value = strToDateForT(valueStr);
                            } catch (Exception e) {
                                // e.printStackTrace();
                            }
                        }else{
                            try {
                                value = strToDate(valueStr, DATETIME_FORMAT);
                            } catch (Exception e) {
                                // e.printStackTrace();
                            }
                        }
                    } else {
                        try {
                            value = strToDate(valueStr, DATE_FORMAT);
                        } catch (Exception e) {
                            // e.printStackTrace();
                        }
                    }
                }
            }
        }
        return value;
    }

    /**
     * 获取当天的开始时间，当天00:00:00.000
     * @since 2018年3月27日
     * @param date
     * @return
     */
    public static Date getCurrentDateS(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        return c.getTime();
    }

    /**
     * 获取当天的结束时间，当天23:59:59.999
     * @since 2018年3月27日
     * @param date
     * @return
     */
    public static Date getCurrentDateE(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.HOUR_OF_DAY, 23);
        c.set(Calendar.MINUTE, 59);
        c.set(Calendar.SECOND, 59);
        c.set(Calendar.MILLISECOND, 999);
        return c.getTime();
    }
}
